package com.bobo.netty.server.websocketchat;

import com.bobo.netty.common.Constants;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class WebSocketChatServerInitializer extends ChannelInitializer<SocketChannel> {
    @Resource
    private TextWebSocketFrameHandler textWebSocketFrameHandler;
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast("logging", new LoggingHandler("DEBUG"));
        /**
         * readerIdleTime读空闲超时时间设定，如果channelRead()方法超过readerIdleTime时间未被调用则会触发超时事件调用userEventTrigger()方法；
         * writerIdleTime写空闲超时时间设定，如果write()方法超过writerIdleTime时间未被调用则会触发超时事件调用userEventTrigger()方法；
         * allIdleTime所有类型的空闲超时时间设定，包括读空闲和写空闲；
         */
        pipeline.addLast(new IdleStateHandler(0,0, Constants.ALL_IDLE_TIME, TimeUnit.SECONDS));
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpObjectAggregator(64*1024));
        pipeline.addLast(new ChannelInboundHandlerAdapter(){
            @Override
            public void userEventTriggered(
                    ChannelHandlerContext ctx, Object evt)
                    throws Exception {
                if(IdleStateEvent.class.isAssignableFrom(evt.getClass())){
                    IdleStateEvent event = (IdleStateEvent) evt;
                    if(event.state() == IdleState.READER_IDLE){
                        System.out.println("read idle");
                    }else if(event.state() == IdleState.WRITER_IDLE) {
                        System.out.println("write idle");
                    }else if(event.state() == IdleState.ALL_IDLE){
                        System.out.println(ctx.channel().id());
                        ChannelFuture channelFuture = ctx.write("close");
                        channelFuture.addListener(ChannelFutureListener.CLOSE);
                    }else {
                        System.out.println("no  idle");
                    }
                }
            }
        });
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpRequestHandler("/ws"));
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        pipeline.addLast(textWebSocketFrameHandler);

    }
}
